<template>
  <div class="app-container">
    <div class="left">
      <div class="move">

        <div style="margin-bottom: 5%;">
          <el-select v-model="device" placeholder="请选择设备" @change="deviceChange">
            <el-option
              v-for="item in deviceList"
              :key="item"
              :label="item.deviceName"
              :value="item">
            </el-option>
          </el-select>
        </div>

        <div class="topTag">
          <el-button type="success" @click="getDevice" style="margin-right:10px;">刷新设备</el-button>
          <el-tag v-if="device.status == '0'" type="danger">设备离线</el-tag>
          <el-tag v-if="device.status == '2'" type="success">设备在线</el-tag>
        </div>



        <div style="margin-bottom: 30px">
          <el-button type="primary"  @click="initWebSocket">重连车辆</el-button>
          <el-button type="primary"  @click="websocketclose">断开连接</el-button>

        </div>

        <div class="joystick-container"  >
          <div  id="joystick_zone"></div>
        </div>

      </div>

      <div class="yuntai">
        <div class="titleView">云台控制</div>
        <div class="referenceBtn"><el-button type="primary" icon="el-icon-refresh-right" @click="resetValue">重置云台</el-button></div>


        <div class="hengController">
          <span class="demonstration">横向移动</span>
          <el-slider style="width: 220px" v-model="crosswiseValue" :max="3000" :min="0" @change="crosswiseChange" ></el-slider>
        </div>

        <div class="shuController">
          <span class="demonstration">上下移动</span>
            <el-slider
            v-model="verticalValue"
            :max="3000"
            :min="0"
            @change="verticalChange"
            vertical
            height="190px">
          </el-slider>
        </div>
      </div>

    </div>
    <div class="control">

      <div class="titleView">实时画面</div>

      <!-- <div class="controlView"> -->
        <!-- <iframe
          src="http://120.79.92.107:8890/"
          style="width: 100%; height: 100%; border: none;"
          frameborder="0"
        ></iframe> -->

        <img v-if="videoFlag" class="controlView" :src="`http://192.168.3.54:6858/video_feed?t=${timestamp}`" width="640" height="480">
        <div v-else class="controlView">
          当前设备未连接
        </div>

      <!-- </div> -->

    </div>

    <div class="right">

      <div class="ledColor">
        <div class="titleView">灯光控制</div>
        <div class="ledColorView">
          <el-switch
            v-model="ledOffOn"
            active-color="#13ce66"
            inactive-color="#ff4949" @change="lefOnChange">led灯开关
          </el-switch>
        </div>
      </div>
      <rgb-color-picker v-if="ledOffOn" v-model="colorValue" @rgb-change="colorChange"></rgb-color-picker>
      <div class="ledColor">
        <div class="titleView">超声波雷达</div>
        <div class="ledColorView">
          <el-switch
            v-model="sonarOffOn"
            active-color="#13ce66"
            inactive-color="#ff4949" @change="sonarOnChange">雷达灯开关
          </el-switch>
        </div>
      </div>
      <div class="ledColor">
        <div class="titleView" style="color: red;" v-if="sonarOffOn && distMsg > 0">前方{{distMsg}}cm,发现障碍物！！！</div>
      </div>
      <div class="ledColor">
        <div class="titleView">智能识物</div>
        <div class="ledColorView">
          <el-switch
            v-model="discernOffOn"
            active-color="#13ce66"
            inactive-color="#ff4949" @change="discernOnChange">
          </el-switch>
        </div>
      </div>


    </div>






  </div>
</template>

<script>
import {gobackward, goforward, goleftward, gorightward} from "@/api/system/robot";
import {getDeviceByName} from "@/api/system/device";
import nipplejs from 'nipplejs';
import RgbColorPicker from '../tool/RgbColorPicker.vue';
export default {
  components: { RgbColorPicker },
  data() {
    return {
      // moveWay : true,
      websock: null, //建立的连接
      lockReconnect: false, //是否真正建立连接
      timeout: 20 * 1000, //20秒一次心跳
      timeoutObj: null, //心跳心跳倒计时
      serverTimeoutObj: null, //心跳倒计时
      timeoutnum: null, //断开 重连倒计时
      msg: "", //显示的值
      sendMsg: "", //输入框的值
      distMsg: "",
      ledOffOn: false, //灯开关
      sonarOffOn: false, //超声波开关
      discernOffOn: false, //智能识别开关
      deviceMove:{
        type: null,
        degree: 0, //角度
        speed: 0, //速度
        crosswiseValue: null,
        verticalValue: null,
        ledOffOn: false,
        rgb: null, //颜色
      },
      device:{
        status: '0', //状态
      },
      deviceList: null,
      crosswiseValue: 1500,
      verticalValue: 1500,
      colorValue: null,
      videoFlag: false,
      timestamp: Date.now()
    }
  },
  created() {
    this.getDevice();
  },
  methods: {
    getDevice(){
      // 保存当前选中的设备ID
      const currentDeviceId = this.device && this.device.deviceId ? this.device.deviceId : null;

      getDeviceByName('car01').then(res =>{
        this.deviceList = res.data;

        if(this.deviceList && this.deviceList.length > 0){
          // 如果有当前选中的设备，尝试在新列表中找到对应的设备
          if(currentDeviceId){
            const selectedDevice = this.deviceList.find(item => item.deviceId === currentDeviceId);
            if(selectedDevice){
              this.device = selectedDevice;
            } else {
              // 如果找不到当前设备，则使用第一个设备
              this.device = this.deviceList[0];
            }
          } else {
            // 如果没有当前设备，则使用第一个设备
            this.device = this.deviceList[0];
          }

          // 更新设备状态和视频显示
          this.videoFlag = this.device.status === '2';
          // 更新时间戳，强制重新加载视频
          this.timestamp = Date.now();
        }
      })
    },
    forward() {
      goforward()
    },
    backward() {
      gobackward()
    },
    leftward() {
      goleftward()
    },
    rightward() {
      gorightward()
    },
    //建立连接，初始化weosocket
    initWebSocket() {

      if(this.device.status == '0'){
        this.videoFlag = false
        this.$message.error('设备离线')
        return;
      }else{
        this.videoFlag = true
      }
      // //后台地址，前面的ws不动，后面是后台地址，我是本地运行的所以填的本地，自行更改。再后面webSocket是后端的接口地址，admin是参数
      // const wsuri = "ws://192.168.31.127:8888";
       const wsuri = "ws://127.0.0.1:3570/ruoyi-vue-service/webSocket/webMove";

      //建立连接
      this.websock = new WebSocket(wsuri);

      this.websock.binaryType = 'arraybuffer';
      //连接成功
      this.websock.onopen = this.websocketonopen;
      //连接错误
      this.websock.onerror = this.websocketonerror;
      //接收信息
      this.websock.onmessage = this.websocketonmessage;
      //连接关闭
      this.websock.onclose = this.websocketclose;
    },
    //连接关闭事件
    websocketclose(e) {
      this.websock.close();
      this.$message.error('连接已关闭')
    },
    reconnect() {
      //重新连接
      var that = this;
      //判断链接状态，true就是链接，false是断开，这里如果是链接状态就不继续执行了，跳出来。
      if (that.lockReconnect) {
        return;
      }
      //把链接状态改为true
      that.lockReconnect = true;
      //没连接上会一直重连，设置延迟避免请求过多
      that.timeoutnum && clearTimeout(that.timeoutnum);
      that.timeoutnum = setTimeout(function () {
        //初始化新连接
        that.initWebSocket();
        //把链接状态改为false
        that.lockReconnect = false;
      }, 5000);
    },
    reset() {
      //重置心跳
      var that = this;
      //清除时间
      clearTimeout(that.timeoutObj);
      clearTimeout(that.serverTimeoutObj);
      //重启心跳
      that.start();
    },
    start() {
      //开启心跳
      var self = this;
      //有延迟时间的就清除掉
      self.timeoutObj && clearTimeout(self.timeoutObj);
      self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
      //从新创建计时器
      self.timeoutObj = setTimeout(function () {
        //这里发送一个心跳，后端收到后，返回一个心跳消息
        if (self.websock.readyState == 1) {
          //如果连接正常发送信息到后台
          self.websock.send("ping");
        } else {
          //否则重连
          self.reconnect();
        }
        self.serverTimeoutObj = setTimeout(function () {
          //超时关闭
          self.websock.close();
        }, self.timeout);
      }, self.timeout);
    },
    //链接成功时执行的方法
    websocketonopen() {
      //连接成功事件
      this.websocketsend("发送数据");
      //提示成功
      console.log("连接成功", 3);
      //开启心跳
      // this.start();
    },
    //连接失败事件
    websocketonerror(e) {
      //错误
      console.log("WebSocket连接发生错误,错误原因",e);
      //重连
      this.reconnect();
    },
    //接收服务器推送的信息
    websocketonmessage(event) {
      //打印收到服务器的内容
      console.log("收到服务器信息", event.data);
      let data = JSON.parse(event.data)
      this.msg = event.data;
      if(data.type = "sonar_dist"){
        console.log("收到距离", data.dist);
        this.distMsg = data.dist;
      }

      // 收到服务器信息，心跳重置
      // this.reset();
    },
    websocketsend(msg) {
      //向服务器发送信息
      this.websock.send(msg);
    },
    // 拖拽结束时触发（值最终确定时）
    crosswiseChange() {
      console.log("crosswiseValue：", this.crosswiseValue);
      this.deviceMove.type = "crosswise"
      this.deviceMove.crosswiseValue = 3000 - this.crosswiseValue;
      // //  console.log(this.deviceMove.degree)
      if (this.device.status === '2') {
          this.websocketsend(JSON.stringify(this.deviceMove));
      }
    },
    verticalChange() {
      console.log("verticalValue：", this.verticalValue);
      this.deviceMove.type = "vertical"
      //因为是反向的，所以这里取反
      this.deviceMove.verticalValue = 3000 - this.verticalValue;
      // //  console.log(this.deviceMove.degree)
      if (this.device.status === '2') {
          this.websocketsend(JSON.stringify(this.deviceMove));
      }
    },
    resetValue(){
      this.deviceMove.type = "reset"
      // //  console.log(this.deviceMove.degree)
      if (this.device.status === '2') {
          this.crosswiseValue = 1500
          this.verticalValue = 1500
          this.websocketsend(JSON.stringify(this.deviceMove));
      }
    },
    colorChange(rgb){
      if (this.device.status === '2') {
          this.deviceMove.type = "color"
          this.deviceMove.rgb = rgb;
          this.websocketsend(JSON.stringify(this.deviceMove));
      }
    },
    lefOnChange(){
      if(this.ledOffOn){
         let rgb = {r: 255, g: 0, b: 0}
         if (this.device.status === '2') {
          this.deviceMove.type = "color"
          this.deviceMove.rgb = rgb;
          this.websocketsend(JSON.stringify(this.deviceMove));
        }
      }else{
        let rgb = {r: 0, g: 0, b: 0}
         if (this.device.status === '2') {
          this.deviceMove.type = "color"
          this.deviceMove.rgb = rgb;
          this.websocketsend(JSON.stringify(this.deviceMove));
        }
      }
    },
    sonarOnChange(){
      if(this.sonarOffOn){
          this.deviceMove.type = "sonaron"
          this.websocketsend(JSON.stringify(this.deviceMove));
      }else{
          this.deviceMove.type = "sonaroff"
          this.websocketsend(JSON.stringify(this.deviceMove));
      }
    },

    discernOnChange(){
      if(this.discernOffOn){
        this.deviceMove.type = "discernOn"
        this.websocketsend(JSON.stringify(this.deviceMove));
      }else{
        this.deviceMove.type = "discernOff"
        this.websocketsend(JSON.stringify(this.deviceMove));
      }
    },
    deviceChange(){
      this.initWebSocket()
    }
  },
  mounted() {

    // //页面刚进入时开启长连接
    // this.initWebSocket();
    setTimeout(() => {
      var options = {
        zone: document.getElementById('joystick_zone'),
        mode: 'static', // 可以选择 'dynamic', 'semi', 或 'static'
        position: { left: '50%', top: '50%' },
        color: 'gray',
      };
      var manager = nipplejs.create(options);

      manager.on('move', (evt, data) => {
        // console.log(data.vector);       // 输出摇杆移动的向量数据（包含x和y分量）
      //  console.log(Math.floor(data.angle.degree));  // 输出摇杆移动的角度（度数，0-360）
       console.log(data.force.toFixed(2));               // 输出摇杆移动的力度（0-1之间的数值）
       // console.log(data.direction);        // 输出摇杆移动的方向（上/下/左/右）
      //  console.log(data.vector.x);         // 输出摇杆向量的x分量（-1到1之间的数值）
       // console.log(data.vector.y);         // 输出摇杆向量的y分量（-1到1之间的数值）

       this.deviceMove.degree = Math.floor(data.angle.degree);

      // //  console.log(this.deviceMove.degree)
       if (this.device.status === '2' && data.force > 0.5 && data.force <= 1) {
        this.deviceMove.type = "move"
        this.websocketsend(JSON.stringify(this.deviceMove));
       }
      });

      manager.on('end', (evt, data) => {
        console.log('摇杆释放');
        // 在这里处理摇杆释放的逻辑
      });
    }, 100);


  },
  destroyed() {
    //页面销毁时关闭长连接
    this.websocketclose();
  },

}
</script>

<style>


.app-container {
  display: flex;
  min-height: 100vh;
  gap: 20px;
  padding: 20px;

  .left {
    flex: 1;
    max-width: 300px;
    .move{
      padding: 20px;

      .topTag{
        margin-bottom: 10px;
      }
      .topBtn{
        margin-bottom: 10px;
      }
    }

    .joystick-container {
        height: 300px;
        margin: 20px;
      }

      #joystick_zone {
        position: relative;
        left: 50%;
        top: 50%;
        width: 200px;
        height: 200px;
        margin-left: -100px;
        margin-top: -100px;
        border: 1px solid #ccc;
        background-color: rgba(255, 255, 144, 0.5);

      }

      .yuntai{
      padding: 20px;
      .titleView{
        height: 40px;
        font-size: 18px;
        font-weight: bold;
        text-align: center;
        color: #c0c0c0;
      }

      .referenceBtn{
        text-align: center;
        margin: 10px 0;
      }

      .hengController{
        display: flex;
        align-items: center;
        gap: 8x;

        .demonstration{
          line-height: 1;
          font-size: 14px;
        }
      }

      .shuController{
        display: flex;
        margin-top: 20px;
        height: 200px;
        text-align: center;

        .demonstration{
          font-size: 14px;
        }

        .el-slider {
          margin: 0 auto;
        }
      }
    }
  }

  .control{
    flex: 2;
    min-width: 640px;
    min-height: 480px;

    .titleView{
      height: 50px;
      font-size: 24px;
      font-weight: bold;
      text-align: center;
    }

    .controlView{
      margin-top: 20px;
      width: 100%;
      height: calc(100vh - 150px);
      border: 1px solid #ccc;
      background-color: rgba(224, 224, 199, 0.5);
    }
    iframe {
      margin: 0 auto;
      width: 90%;
      height: 90%;
    }
  }

  .right{
    flex: 1;
    min-width: 250px;

    .ledColor{
      display: flex;

      .titleView{
        margin-right: 20px;
      }
    }
  }
}



</style>
